package com.weipu.common.okhttp;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import org.apache.http.conn.ConnectTimeoutException;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import com.squareup.okhttp.Callback;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.weipu.common.DXApplication;
import com.weipu.common.constants.Constant;
import com.weipu.common.constants.ServerConstant;
import com.weipu.common.facade.exception.DxException;
import com.weipu.common.util.NetWorkUtil;

/**
 * Okhttp异步请求数据时的回调对象 CallBack
 * @author huangfei 
 *
 */
public abstract class DxOkHttpCallback implements Callback {
	//主线程Handler
	private Handler uiHandler = new Handler(Looper.getMainLooper()) {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case 0:// 请求失败
				String status = (String) msg.obj;
				onTaskFinish(status, null);
				break;
			case 1:// 请求成功
				Object obj = msg.obj;
				onTaskFinish("0", obj);
				break;

			default:
				break;
			}

		};
	};

	@Override
	public void onFailure(Request request, IOException e) {
		dealException(e);
	}

	/**
	 * Okhttp网络请求数据返回接口 运行在子线程 该类子类方法不能覆盖该方法的实现逻辑
	 */
	@Override
	public void onResponse(Response response) {
		try {
			if (response.isSuccessful()) {
				String result = response.body().string();
				String status = "0";
				JSONObject resultObject = null;
				try {
					resultObject = returnResult(result);
				} catch (DxException e) {
					status = e.getErrCode();
				}
				//解析Json对象为Bean
				Object object = parserBeanTask(status, resultObject);
				Message message = uiHandler.obtainMessage();
				if ("0".equals(status)) {
					message.obj = object;
					message.what = 1;
					uiHandler.sendMessage(message);
					//请求成功后做一些耗时的操作 如保存数据
					doSomethingTask(object);
				} else {
					message.obj = status;
					uiHandler.sendEmptyMessage(0);
				}

			} else {//response 失败
				Message message = uiHandler.obtainMessage();
				message.obj = ServerConstant.ReturnCode.VALIDATOR_UNKONW_ERROR;
				uiHandler.sendEmptyMessage(0);
			}
		} catch (IOException e) {
			dealException(e);
		}

	}

	/**
	 * 对数据进行异常捕获
	 * 
	 * @param result
	 * @return
	 * @throws DxException
	 *             [参数说明]
	 * @return JSONObject [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public JSONObject returnResult(String result) throws DxException {
		JSONObject json = null;
		if (null == result) {
			return null;
		}
		try {
			json = new JSONObject(result);
		} catch (JSONException e) {
			throw new DxException(
					ServerConstant.ReturnCode.STATUS_INTENAL_ERROR);
		}
		String status = json.optString(Constant.JSON_STATUS);
		// 请求到的数据无效
		if (null == status) {
			throw new DxException(
					ServerConstant.ReturnCode.STATUS_INTENAL_ERROR);
		}
		// 向外抛出异常
		if (!"0".equals(status)) {
			throw new DxException(status);
		}
		return json;
	}

	/**
	 * 处理请求抛出的异常
	 * @param e 具体异常
	 */
	private void dealException(IOException e) {
		Message message = uiHandler.obtainMessage();
		message.obj = ServerConstant.ReturnCode.VALIDATOR_UNKONW_ERROR;
		if (e.getCause() instanceof SocketTimeoutException
				|| e.getCause() instanceof ConnectTimeoutException) {
			message.obj = ServerConstant.ReturnCode.VALIDATOR_CONNECT_TIMEOUT;
		} else if (e.getCause() instanceof UnknownHostException) {
			message.obj = ServerConstant.ReturnCode.CLIENT_NET_UN_AVAILABLE;
		} else {
			if (!NetWorkUtil.isNetworkAvailable(DXApplication.getContext())) {
				message.obj = ServerConstant.ReturnCode.CLIENT_NET_UN_AVAILABLE;
			} else {
				message.obj = ServerConstant.ReturnCode.VALIDATOR_UNKONW_ERROR;
			}
		}
		uiHandler.sendEmptyMessage(0);
	}

	/**
	 * 网络请求结束后 可以处理一些耗时的操作 运行在子线程中
	 * @param object 解析后的数据Bean对象
	 */
	protected abstract void doSomethingTask(Object object);

	/**
	 * 网络请求结束后 解析对应的Bean对象 运行在子线程
	 * @param status 返回结果状态
	 * @param response 网络请求返回的全部Json数据
	 * @return
	 */
	protected abstract Object parserBeanTask(String status, JSONObject response);

	/**
	 * 网络网络请求结束后 处理UI刷新操作 运行在主线程
	 * @param status 返回结果状态
	 * @param object 解析后的数据Bean对象
	 */
	protected abstract void onTaskFinish(String status, Object object);

}
